<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>设计模式</title>
</head>

<body>
  <h2>发布订阅模式</h2>
  <button class="on">注册事件</button>
  <button class="emit">触发事件</button>
  <button class="off">移除事件</button>
  <button class="once-on">一次性事件注册</button>
  <button class="once-emit">一次性事件触发</button>
  <script>
    class HMEmmiter {
      // 1.1 添加私有属性
      #handlers = {
        // 事件名:[callback1,callback2]
      }


      /**
       * 添加事件监听:
       *  1.1 添加私有属性
       *  1.2 保存事件
       */
      $on(event, callback) {
        // 1.2 保存事件
        if (this.#handlers[event] === undefined) {
          this.#handlers[event] = []
        }
        this.#handlers[event].push(callback)
      }


      /**
       * 触发事件:
       *  2.1 接收不定长参数
       *  2.2 循环触发事件
       * */
      // 2.1 接收不定长参数
      $emit(event, ...args) {
        // 2.2 循环触发事件
        const funcs = this.#handlers[event] || []
        funcs.forEach(callback => {
          callback(...args)
        })
      }

      /**
       * 移除事件:
       *  3.1 清空事件
       * */
      $off(event) {
        // 3.1 清空事件
        this.#handlers[event] = undefined
      }

      /**
       * 一次性事件
       *  4.1 调用$on注册事件
       *  4.2 事件内调用$off
       * */
      $once(event, callback) {
        // 4.1 调用$on注册事件
        this.$on(event, (...args) => {
          callback(...args)
          // 4.2 事件内调用$off
          this.$off(event)
        })
      }
    }

    const bus = new HMEmmiter()


    // 注册事件
    document.querySelector('.on').addEventListener('click', () => {
      bus.$on('event1', () => { console.log('回调函数1') })
      bus.$on('event2', (name, info) => { console.log(name, info) })
      bus.$on('event2', (name, info) => { console.log('event2的第二个回调函数', name, info) })
    })
    // 触发事件
    document.querySelector('.emit').addEventListener('click', () => {
      bus.$emit('event1')
      bus.$emit('event2', 'itheima', '666')
    })
    // 移除事件
    document.querySelector('.off').addEventListener('click', () => {
      bus.$off('event2')
    })
    // 一次性事件注册
    document.querySelector('.once-on').addEventListener('click', () => {
      bus.$once('once-event', (name, info) => {
        console.log(name, info)
      })
    })
    // 一次性事件触发
    document.querySelector('.once-emit').addEventListener('click', () => {
      bus.$emit('once-event', 'itheima', '666')
    })

  </script>
</body>

</html>